package com.xqboss.apps.service.consumer;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xqboss.apps.domain.consumer.ConsumerTeamMember;
import com.xqboss.apps.dto.consumer.ConsumerTeamDto;
import com.xqboss.apps.dto.consumer.ConsumerTeamMsgRecordDto;
import com.xqboss.apps.dto.team.TeamInviteJoinDto;
import com.xqboss.apps.enums.consumer.ConsumerApplyTypeEnum;
import com.xqboss.apps.enums.consumer.ConsumerTeamMemberTypeEnum;
import com.xqboss.apps.enums.consumer.ConsumerTeamRoleEnum;
import com.xqboss.apps.mapper.consumer.ConsumerTeamMemberMapper;
import com.xqboss.apps.vo.consumer.ConsumerTeamMemberFamilyVo;
import com.xqboss.apps.vo.consumer.ConsumerTeamMemberReminderVo;
import com.xqboss.apps.vo.consumer.ConsumerTeamMemberVo;
import com.xqboss.apps.vo.consumer.ConsumerTeamVo;
import com.xqboss.apps.vo.team.WebConsumerTeamMemberFamilyVo;
import com.xqboss.common.constant.HttpStatus;
import com.xqboss.common.core.domain.R;
import com.xqboss.common.core.domain.entity.SysUser;
import com.xqboss.common.exception.ServiceException;
import com.xqboss.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 队伍成员Service业务层处理
 *
 * @author xqboss
 * @date 2023-08-15
 */
@Service
public class ConsumerTeamMemberService extends ServiceImpl<ConsumerTeamMemberMapper, ConsumerTeamMember> {

    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ConsumerTeamService consumerTeamService;
    @Autowired
    private ConsumerService consumerService;

    /**
     * 获取用户的队伍 id
     *
     * @return
     */
    public Long getTeamIdByUserId(Long userId) {
        LambdaQueryWrapper<ConsumerTeamMember> wq = new LambdaQueryWrapper<>();
        wq.eq(ConsumerTeamMember::getUserId, userId);
        wq.last("LIMIT 1");
        ConsumerTeamMember teamMember = getOne(wq);
        if (ObjUtil.isNull(teamMember)) {
            return null;
        }
        return Long.valueOf(teamMember.getTeamId());
    }

    /**
     * 获取用户的队伍(成员)信息
     *
     * @return
     */
    public ConsumerTeamMember getTeamMemberByUserId(Long userId) {
        LambdaQueryWrapper<ConsumerTeamMember> wq = new LambdaQueryWrapper<>();
        wq.eq(ConsumerTeamMember::getUserId, userId);
//        wq.last("LIMIT 1");
        ConsumerTeamMember teamMember = getOne(wq);
        if (ObjUtil.isNull(teamMember)) {
            return null;
        }
        return teamMember;
    }

    /**
     * 判断该用户是否为队长
     *
     * @param userId 用户id
     * @return true-队长 false-成员
     */
    public boolean isRole_1(Long userId) {
        LambdaQueryWrapper<ConsumerTeamMember> wq = new LambdaQueryWrapper<>();
        wq.eq(ConsumerTeamMember::getUserId, userId);
        wq.eq(ConsumerTeamMember::getRole, 1);
        wq.last("LIMIT 1");
        ConsumerTeamMember teamMember = getOne(wq);
        return ObjUtil.isNotNull(teamMember);
    }


    /**
     * 注册-邀请加入队伍
     *
     * @param userId
     * @param params
     * @return
     */
    public R inviteJoinTeam(Long userId, TeamInviteJoinDto params) {
        //校验是否已注册
        SysUser currentUser = sysUserService.selectUserById(userId);
        if (StrUtil.isNotBlank(params.getUserName())) { //新用户注册后加入队伍 当前登录用户与userid 从新赋值
            currentUser = sysUserService.selectUserByUserName(params.getUserName());
            userId = currentUser.getUserId();
        }
        if (Objects.isNull(currentUser)) {
            return R.fail("注册后才能加入队伍");
        }
        //若 被邀请者 已加入了其他队伍则提示【您已加入其他队伍，请退出队伍后再试】
        ConsumerTeamVo currentTeam = consumerTeamService.getBaseMapper().getMyTeam(userId);
        if (Objects.nonNull(currentTeam)) {
            if (currentTeam.getMemberType() != ConsumerTeamMemberTypeEnum.TYPE_MAIN) {
                return R.fail("您已与其他账户绑定亲属关系，请解除后再试");
            }
            return R.fail("您已加入其他队伍，请退出队伍后再试");
        }
        //邀请人
        SysUser inviteUser = sysUserService.selectUserByInvitationCode(params.getInvitationCode());
        if (Objects.isNull(inviteUser)) {
            return R.fail("邀请人不存在，无法加入");
        }
        ConsumerTeamVo inviteTeam = consumerTeamService.getBaseMapper().getMyTeam(inviteUser.getUserId());
        if (Objects.isNull(inviteTeam)) {
            return R.fail("邀请人不在队伍中，无法加入");
        }
        if (inviteTeam.getMemberCount() >= inviteTeam.getMaxNumber()) {
            return R.fail("队伍已满员，无法加入");
        }
        //校验当前亲属位是否空缺
        if (params.getType() != ConsumerTeamMemberTypeEnum.TYPE_MAIN) {
            ConsumerTeamMember teamMember = getTeamMemberByIdAndType(inviteTeam.getId(), inviteUser.getUserId(), params.getType());
            if (Objects.nonNull(teamMember)) {
                return R.fail("邀请人亲属位已有人，无法加入");
            }
        }
        //加入队伍
        ConsumerTeamMsgRecordDto dto = new ConsumerTeamMsgRecordDto();
        dto.setTeamId(Math.toIntExact(inviteTeam.getId()));
        dto.setUserId(userId);
        dto.setMemberType(params.getType());
        //邀请主成员
        if (params.getType() == ConsumerTeamMemberTypeEnum.TYPE_MAIN) {
            dto.setApplyTypeEnum(ConsumerApplyTypeEnum.USER_APPLY);
        }
        dto.setInviteId(inviteUser.getUserId());
        R res = consumerTeamService.joinTeam(dto);
        //当前用户如果没有绑定上级，就绑定上下级关系
        if (currentUser.getInviterId() == null) {
            R r = consumerService.bindInvite(currentUser.getUserId(), params.getInvitationCode());
            if (r.getCode() != HttpStatus.SUCCESS) {
                return  r;
            }
        }
        return res;
    }

    /**
     * 如果当前退出成员为主成员，返回该主成员和家庭成员信息
     *
     * @param teamId 队伍id
     * @param userId 用户id （需要判断是否为主成员）
     * @return 该主成员和家庭成员信息
     */
    public List<ConsumerTeamMemberVo> isMainMemberReturnFamilyMembers(Integer teamId, Long userId) {
        Long adminRole = this.lambdaQuery()
                .eq(ConsumerTeamMember::getTeamId, teamId)
                .eq(ConsumerTeamMember::getUserId, userId)
                .eq(ConsumerTeamMember::getRole, ConsumerTeamRoleEnum.ADMINISTRATOR.getValue())
                .count();
        Long mainType = this.lambdaQuery()
                .eq(ConsumerTeamMember::getTeamId, teamId)
                .eq(ConsumerTeamMember::getUserId, userId)
                .eq(ConsumerTeamMember::getType, ConsumerTeamMemberTypeEnum.TYPE_MAIN)
                .count();
        if (adminRole==0 && mainType==0) {//是队长或主成员就可以退出队伍
            throw new ServiceException("您不是主成员，不能退出队伍！");
        }
        // 获取主成员的家属(包括主成员)
        return this.getBaseMapper().selectBasicInfos(teamId, userId);
    }

    /**
     * 如果当前退出成员为主成员，返回该主成员和家庭成员信息
     *
     * @param teamId       队伍id
     * @param secureUserId 需要解除亲属关系的亲属用户id
     * @param userId       用户id （需要判断是否为主成员）
     * @return 该主成员和家庭成员信息
     */
    public List<ConsumerTeamMemberVo> isMainMemberReturnFamilyMember(Integer teamId, Long secureUserId, Long userId) {
        if (Objects.equals(secureUserId, userId)) {
            throw new ServiceException("您是主成员，您不能解除自己！");
        }
        Long mainType = this.lambdaQuery()
                .eq(ConsumerTeamMember::getTeamId, teamId)
                .eq(ConsumerTeamMember::getUserId, userId)
                .eq(ConsumerTeamMember::getType, ConsumerTeamMemberTypeEnum.TYPE_MAIN)
                .count();
        if (mainType == 0) {
            throw new ServiceException("您不是主成员，不能解除家庭亲属关系！");
        }
        // 验证该主成员是否为队长，是的话可以解除所有人
        Long adminRole = this.lambdaQuery()
                .eq(ConsumerTeamMember::getTeamId, teamId)
                .eq(ConsumerTeamMember::getUserId, userId)
                .eq(ConsumerTeamMember::getRole, ConsumerTeamRoleEnum.ADMINISTRATOR.getValue())
                .count();
        if (adminRole != 0) {
            //是队长则获取到该成员信息或家庭成员信息
            return this.getBaseMapper().selectBasicInfos(teamId, secureUserId);
        }else{
            //不是队长，则是解除自己的家庭成员
            return Collections.singletonList(this.getBaseMapper().selectBasicInfo(teamId, userId, secureUserId));
        }
    }

    /**
     * 返回所踢队员的基本信息
     * <p>
     * 1.踢的队员是——主成员，返回包括主成员在内的其家庭成员信息
     * 2.踢的队员是——非主成员，返回该成员信息
     *
     * @param teamId     队伍id
     * @param kickUserId 要踢的队员用户id（需要判断是主成员还是非主成员）
     * @param userId     用户id(需要判断是否为队长-管理员)
     * @return 成员信息
     */
    public List<ConsumerTeamMemberVo> isMainMemberReturnFamilyMemberOrMore(Integer teamId, Long kickUserId, Long userId) {
        if (Objects.equals(kickUserId, userId)) {
            throw new ServiceException("您是队长，您不能踢出自己！");
        }
        Long adminRole = this.lambdaQuery()
                .eq(ConsumerTeamMember::getTeamId, teamId)
                .eq(ConsumerTeamMember::getUserId, userId)
                .eq(ConsumerTeamMember::getRole, ConsumerTeamRoleEnum.ADMINISTRATOR.getValue())
                .count();
        if (adminRole == 0) {
            throw new ServiceException("您不是队长，不可以从队伍中踢人！");
        }
        Long mainType = this.lambdaQuery()
                .eq(ConsumerTeamMember::getTeamId, teamId)
                .eq(ConsumerTeamMember::getUserId, kickUserId)
                .eq(ConsumerTeamMember::getType, ConsumerTeamMemberTypeEnum.TYPE_MAIN)
                .count();
        if (mainType!=0) {
            //要踢的人为——主成员,获取主成员的家属(包括主成员)
            return this.getBaseMapper().selectBasicInfos(teamId, kickUserId);
        }else{
            return Collections.singletonList(this.getBaseMapper().selectBasicInfo(teamId, userId, kickUserId));
        }
    }

    /**
     * 查询指定队伍家庭所有成员(包括当日解除家庭关系的成员，以及退出队伍的队长或主成员)
     *
     * @param teamId 队伍id
     * @param date 当日
     * @return 家庭信息
     */
    public List<ConsumerTeamMemberFamilyVo> selectTeamMembers(Integer teamId, LocalDate date) {
        Optional.ofNullable(teamId).orElseThrow(()->new ServiceException("队伍id不能为空！"));
        // 查询队伍所有成员主要数据
        List<ConsumerTeamMemberFamilyVo> vo = getBaseMapper().selectTeamMembers(teamId,date);

        return Optional.of(vo).orElse(null);
    }

    /**
     * 队伍详情【成员信息】
     * @param params
     * @return
     */
    public List<WebConsumerTeamMemberFamilyVo> infoMembers(ConsumerTeamDto params) {
        if (params.getId() == null) {
            throw new ServiceException("队伍id不能为空！");
        }
        params.startPage();
        List<WebConsumerTeamMemberFamilyVo> voList = this.getBaseMapper().infoMembers(params);
        // 2.过滤出主成员
        List<WebConsumerTeamMemberFamilyVo> mainMembers = voList.stream().filter(t -> t.getType() == ConsumerTeamMemberTypeEnum.TYPE_MAIN).collect(Collectors.toList());
        // 3.筛选出主成员的家庭成员
        List<WebConsumerTeamMemberFamilyVo> familyMembers;
        for (WebConsumerTeamMemberFamilyVo mainMember : mainMembers) {
            familyMembers = voList.stream().filter(t -> Objects.equals(mainMember.getUserId(), t.getParentId())).collect(Collectors.toList());
            mainMember.setChildren(familyMembers);
        }
        return  mainMembers;
    }

    /**
     *
     * 获取被提醒方的基本信息
     *
     * @param teamId 队伍id
     * @param reminderUserId 提醒方用户id
     * @param toReminderUserId 被提醒方用户id
     * @return ConsumerTeamMemberReminderVo
     */
    public ConsumerTeamMemberReminderVo teamMemberReminderInfo(Long teamId,Long reminderUserId,Long toReminderUserId){
        Optional.ofNullable(teamId).orElseThrow(()->new ServiceException("队伍id不能为空！"));
        Optional.ofNullable(reminderUserId).orElseThrow(()->new ServiceException("提醒方用户id不能为空！"));
        Optional.ofNullable(toReminderUserId).orElseThrow(()->new ServiceException("被提醒方用户id不能为空！"));
        return getBaseMapper().teamMemberReminderInfo( teamId, reminderUserId, toReminderUserId);
    }

    /**
     * 根据亲属类型获取成员
     * @param teamId 队伍id
     * @param userId 用户id
     * @param memberTypeEnum 成员类型
     */
    public ConsumerTeamMember getTeamMemberByIdAndType(Long teamId, Long userId, ConsumerTeamMemberTypeEnum memberTypeEnum) {
        return this.getOne(new LambdaQueryWrapper<ConsumerTeamMember>()
                .eq(ConsumerTeamMember::getTeamId, teamId)
                .eq(ConsumerTeamMember::getParentId, userId)
                .eq(ConsumerTeamMember::getType, memberTypeEnum));
    }
}
